//
//  ctrlVersion.cpp
//  lilTerm
//
//  Created by Threese on 2019/7/20.
//  Copyright © 2019 Threese. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

//const attribute
static const int NAME_SIZE = 30;//name charArray limit
static const int LABEL_SIZE = 100;//label charArray limit
static const int PLAN_SIZE = 20;//planArray limit

typedef struct date {
    int year = 0;
    int month = 0;
    int day = 0;
}D;
int compareDate(D d1, D d2);
void printDate(date d);
void copyDate(date *dst, date src);

typedef struct task {
    char name [NAME_SIZE] = "";
    char label [LABEL_SIZE] = "";
    D sTime;
    D eTime;
    int importance = 1;
    //basic arrtibutes
    
    task * nextTask = NULL;
    task * previousTask = NULL;
}T;
void printTask(task *t);
void copyTask(T *dst, T src);
void copyTask(T *dst, T *src);

typedef struct plan {
    char name [NAME_SIZE] = "";
    char label [LABEL_SIZE] = "";
    D sTime;
    D eTime;
    
    int taskNum = 0;
    T *headTask = NULL;
}P;
void addTask(plan *p, task *t);
int removeTask(P *p, int index);
void printPlan(plan p);
void copyPlan(plan *dst, plan src);

time_t timer = time(NULL);
int year;
int month;
int day;

P plans [PLAN_SIZE];
int plansNum = 0;

void instruction( );
void planInstruction( );
void ePlanInstruction( );
void eTaskInstruction( );

void seeTime( );
void getToday();
void seeTask( );
void createTask(P *p);

void checkPlan( );
void printPlans( );
void createPlan( );
void deletePlan( );

void editPlan();
void editPlanName(int);
void editPlanLabel(int indexOfPlan);
void editPlanStartTime(int);
void editPlanEndTime(int);

void editTask(int indexOfPlan,int indexOfTask);
void editTaskName(int indexOfPlan,int indexOfTask);
void editTaskLabel(int indexOfPlan,int indexOfTask);
void editTaskStartTime(int indexOfPlan,int indexOfTask);
void editTaskEndTime(int indexOfPlan,int indexOfTask);
void editTaskImportance(int indexOfPlan,int indexOfTask);
bool setTaskImportance(P *p,int index);

T* getTask(int indexOfPlan,int indexOfTask);

int main( ){
    instruction();
    int command = -1;
    
    while (command != 0) {
        scanf("%d",&command);
        
        switch (command) {
            case 1:
                seeTime();
                break;
            case 2:
                seeTask();
                break;
            case 3:
                checkPlan();
                break;
            case 4:
                //TODO open file
                break;
            case 5:
                //TODO save file
                break;
            case 6:
                instruction();
                break;
            default:
                break;
        }
    }
    
    printf("*** program end successfully ***\n");
}

void editPlan(int index){
    if (index<0||index>=plansNum)
    {
        printf("index cross-border\n");
        return;
    }
    ePlanInstruction();
    int command = -1;
    int indexOfTask = 0;
    while (command != 0) {
        scanf("%d",&command);
        
        switch (command) {
            case 1:
                editPlanName(index);
                break;
            case 2:
                editPlanLabel(index);
                break;
            case 3:
                editPlanStartTime(index);
                break;
            case 4:
                editPlanEndTime(index);
                break;
            case 5:
                createTask(&plans[index]);
                break;
            case 6:
                printf("please enter index of Task!\n");
                scanf("%d",&indexOfTask);
                removeTask(&plans[index],indexOfTask    );
                break;
            case 7:
                printf("please enter index of Task!\n");
                scanf("%d",&indexOfTask);
                editTask(index,indexOfTask);
                break;
            case 8:
                ePlanInstruction();
                break;
            default:
                break;
        }
    }
    planInstruction();
}

void deletePlan( ){
    printf("*** enter the index ***\n");
    int index = 0;
    scanf("%d",&index);
    if(index < 0 || index >= plansNum)
        printf("*** invalid index ***\n");
    else{
        plan temps [PLAN_SIZE];
        int count = 0;
        for(int i = 0;i <= plansNum;i++){
            if(i == index)
                continue;
            else{
                copyPlan(&temps[count], plans[i]);
                count++;
            }
        }
        
        plansNum = count;
        plan empty;
        for(int i = 0;i < PLAN_SIZE;i++){
            if(i < count)
                copyPlan(&plans[i], temps[i]);
            else
                copyPlan(&plans[i], empty);
        }
        
        plansNum--;
    }
}//DONE

void createPlan( ){
    if(plansNum == 19)
        printf("*** the number of plans has reached limit ***");
    else{
        char tName [NAME_SIZE] = "";
        char tLabel [LABEL_SIZE] = "";
        date tSTime;
        date tETime;
        
        printf("name: ");
        scanf("%29s",tName);
        printf("label: ");
        scanf("%99s",tLabel);
        printf("startTime\nyear:");
        scanf("%d",&tSTime.year);
        printf("month: ");
        scanf("%d",&tSTime.month);
        printf("day: ");
        scanf("%d",&tSTime.day);
        printf("endTime\nyear:");
        scanf("%d",&tETime.year);
        printf("month: ");
        scanf("%d",&tETime.month);
        printf("day: ");
        scanf("%d",&tETime.day);
        
        plan newPlan;
        newPlan.headTask = NULL;
        strcpy(newPlan.name, tName);
        strcpy(newPlan.label, tLabel);
        copyDate(&newPlan.sTime, tSTime);
        copyDate(&newPlan.eTime, tETime);
        
        copyPlan(&plans[plansNum], newPlan);
        plansNum++;
    }
}

void printPlans( ){
    if(plansNum == 0)
        printf("*** the system has no plan ***\n");
    else{
        for(int i = 0;i < plansNum;i++){
            printPlan(plans[i]);
        }
    }
}

void checkPlan( ){
    planInstruction();
    int command = -1;
    int index = 0;
    while(command != 0){
        scanf("%d",&command);
        
        switch (command) {
            case 1:
                printPlans();
                break;
            case 2:
                printf("please enter index of plan\n");
                scanf("%d",&index);
                editPlan(index);
                //editPlan();
                break;
            case 3:
                createPlan();
                break;
            case 4:
                deletePlan();
                break;
            case 5:
                planInstruction();
                break;
            default:
                break;
        }
    }
    instruction();
}

void seeTask( ){
    getToday();
    
    D today;
    today.year = year;
    today.month = month;
    today.day = day;
    
    bool empty = true;
    
    for(int i = 0;i <= plansNum;i++){
        T *ptr = plans[i].headTask;
        while(ptr != NULL){
            if(compareDate(ptr->sTime, today) <= 0
               && compareDate(ptr->eTime, today) >= 0){
                printTask(ptr);
                empty = false;
                
                ptr = ptr->nextTask;
            }
        }
    }
    
    if(empty)
        printf("*** today has no task ***\n");
}

void seeTime( ){
    timer = time(NULL);
    struct tm *time = localtime(&timer);
    printf("*** %.4d/%.2d/%.2d\t%d:%d:%d ***\n", time->tm_year + 1900,
           time->tm_mon + 1, time->tm_mday, time->tm_hour,
           time->tm_min, time->tm_sec);
}

void getToday(){
    timer = time(NULL);
    struct tm *time = localtime(&timer);
    
    year = time->tm_year + 1900;
    month = time->tm_mon + 1;
    day = time->tm_mday;
}

void editTask(int indexOfPlan,int indexOfTask)
{
     if (indexOfTask<0||indexOfTask>(plans+indexOfPlan)->taskNum)
    {
        printf("index of task cross-border\n");
        return;
    }
    editPlanEndTime(indexOfPlan);
   
   int command = -1;
    while (command != 0) {
        scanf("%d",&command);
        
        switch (command) {
            case 1:
                editTaskName(indexOfPlan,indexOfTask);
                break;
            case 2:
                editTaskLabel(indexOfPlan, indexOfTask);
                break;
            case 3:
               editTaskStartTime(indexOfPlan,indexOfTask);
                break;
            case 4:
                editTaskEndTime(indexOfPlan,indexOfTask);
                break;
            case 5:
                setTaskImportance(&plans[indexOfPlan],indexOfTask);
                break;
            case 6:
                printTask(getTask(indexOfPlan,indexOfTask));
                break;
            case 7:
                 eTaskInstruction();
                break;
            default:
                break;
        }
        eTaskInstruction();
    }

}
//method for Date
int compareDate(D d1, D d2){
    if(d1.year > d2.year)
        return 1;
    else if(d1.year == d2.year){
        if(d1.month > d2.month)
            return 1;
        else if(d1.month == d2.month){
            if(d1.day > d2.day)
                return 1;
            else if(d1.day == d2.day)
                return 0;
            else
                return -1;
        }
        else
            return -1;
    }
    else
        return -1;
}
//d1 > d2 return 1, d1 == d2 return 0,d1 < d2 return -1

void printDate(date d){
    printf("%4d/%.2d/%.2d",d.year,d.month,d.day);
}
//exp: 2019/07/20

void copyDate(date *dst, date src){
    dst->year = src.year;
    dst->month = src.month;
    dst->day = src.day;
}

//method for task
void printTask(task *t){
    if(t){
        printf("name: %s\n",t->name);
        printf("label: %s\n",t->label);
        printf("startTime: ");
        printDate(t->sTime);
        printf("\nendTime: ");
        printDate(t->eTime);
        printf("\nimportance: %.1d\n",t->importance);
    }
}

void addTask(plan *p, task *t){
    T *ptr = p->headTask;
    
    while(ptr->nextTask != NULL){
        ptr = ptr->nextTask;
    }
    
    ptr->nextTask = t;
    t->previousTask = ptr;
    
    p->taskNum++;
}

int removeTask(P *p, int index){
    T *ptr = p->headTask;
    
    if(index < 0 || index >= p->taskNum)
        return 0;
    
    int count = 0;
    while(ptr != NULL){
        if(index == count){
            ptr->nextTask->previousTask = ptr->previousTask;
            ptr->previousTask->nextTask = ptr->nextTask;
            
            //printf("T1: %s\nT2: %s\nTX: %s\n", ptr->previousTask->name, ptr->nextTask->name, ptr->previousTask->nextTask->name);
            
            free(ptr);
            
            return 1;
        }
        
        ptr = ptr->nextTask;
        count++;
    }
    
    return 0;
}

void copyTask(T *dst, T src){
    strcpy(dst->name, src.name);
    strcpy(dst->label, src.label);
    copyDate(&dst->sTime, src.sTime);
    copyDate(&dst->eTime, src.eTime);
    dst->importance = src.importance;
    dst->nextTask = src.nextTask;
    dst->previousTask = src.previousTask;
}//copy only content, no pointer

void copyTask(T *dst, T *src){
    strcpy(dst->name, src->name);
    strcpy(dst->label, src->label);
    copyDate(&dst->sTime, src->sTime);
    copyDate(&dst->eTime, src->eTime);
    dst->importance = src->importance;
    dst->nextTask = src->nextTask;
    dst->previousTask = src->previousTask;
}//copy only content, no pointer

//method for plan
void printPlan(plan p){
    printf("name: %s\n",p.name);
    printf("label: %s\n",p.label);
    printf("startTime: ");
    printDate(p.sTime);
    printf("\nendTime: ");
    printDate(p.eTime);
    printf("\n");
    
    int count = 0;
    T *ptr = p.headTask;
    
    //printf("%p\n", ptr);
    
    while(ptr) {
        printf("task %d\n",count);
            printTask(ptr);
        
        ptr = ptr->nextTask;
        count++;
        //printf("%d",count);
        //TODO
    }
}

void copyPlan(plan *dst, plan src){
    strcpy(dst->name, src.name);
    strcpy(dst->label, src.label);
    copyDate(&dst->sTime, src.sTime);
    copyDate(&dst->eTime, src.eTime);
    
    T *ptr = dst->headTask;
    while(ptr != NULL){
        T * temp = ptr;
        ptr = ptr->nextTask;
        free(temp);
    }
    
    ptr = dst->headTask;
    T *srcPtr = src.headTask;
    while(srcPtr != NULL){
        ptr = (T*)malloc(sizeof(struct task));
        copyTask(ptr, srcPtr);
        
        srcPtr = srcPtr->nextTask;
    }
    
    dst->taskNum = src.taskNum;
}//real copy

void editPlanName(int index)
{
    char tName[NAME_SIZE];
    printf("name: ");
    scanf("%29s",tName);
    strcpy((plans+index)->name,tName);
}

void editPlanLabel(int index)
{
    char tLabel[LABEL_SIZE];
    printf("label: ");
    scanf("%s99",tLabel);
    strcpy((plans+index)->label,tLabel);
}
void editPlanStartTime(int index)
{
    date tSTime;
    printf("startTime\nyear:");
    scanf("%d",&tSTime.year);
    printf("month: ");
    scanf("%d",&tSTime.month);
    printf("day: ");
    scanf("%d",&tSTime.day);
    copyDate(&(plans+index)->sTime,tSTime);
}
void editPlanEndTime(int index)
{
    date tETime;
    printf("startTime\nyear:");
    scanf("%d",&tETime.year);
    printf("month: ");
    scanf("%d",&tETime.month);
    printf("day: ");
    scanf("%d",&tETime.day);
    copyDate(&(plans+index)->eTime,tETime);
}
void editTaskName(int indexOfPlan,int indexOfTask)
{
    T *ptr = (plans+indexOfPlan)->headTask;
    int count = 0;
    char tName[NAME_SIZE];
    scanf("%29s",tName);
    while(ptr != NULL){
        if(indexOfTask == count){
            strcpy(ptr->name,tName);
         }
        ptr = ptr->nextTask;
        count++;
    }
}
void editTaskLabel(int indexOfPlan,int indexOfTask)
{
    T *ptr = (plans+indexOfPlan)->headTask;
    int count = 0;
    char tLabel[LABEL_SIZE];
    scanf("%99s",tLabel);
    while(ptr != NULL){
        if(indexOfTask == count){
            strcpy(ptr->label,tLabel);
         }
        ptr = ptr->nextTask;
        count++;
    }
}
void editTaskStartTime(int indexOfPlan,int indexOfTask)
{
    T *ptr = (plans+indexOfPlan)->headTask;
    date tSTime;
    int count = 0;
    printf("startTime\nyear:");
    scanf("%d",&tSTime.year);
    printf("month: ");
    scanf("%d",&tSTime.month);
    printf("day: ");
    scanf("%d",&tSTime.day);
    
     while(ptr != NULL){
        if(indexOfTask == count){
            copyDate(&ptr->sTime,tSTime);
         }
        ptr = ptr->nextTask;
        count++;
    }
}
void editTaskEndTime(int indexOfPlan,int indexOfTask)
{
    T *ptr = (plans+indexOfPlan)->headTask;
    date tETime;
    int count = 0;
    printf("startTime\nyear:");
    scanf("%d",&tETime.year);
    printf("month: ");
    scanf("%d",&tETime.month);
    printf("day: ");
    scanf("%d",&tETime.day);
    
     while(ptr != NULL){
        if(indexOfTask == count){
            copyDate(&ptr->eTime,tETime);
         }
        ptr = ptr->nextTask;
        count++;
    }
}

T* getTask(int indexOfPlan,int indexOfTask)
{
    T *t = (plans+indexOfPlan)->headTask;
    int count = 0;
            
    while(t != NULL){
        if(indexOfTask == count){
            return t;
        }
            t = t->nextTask;
            count++;
    }
    
    return NULL;
}

bool setTaskImportance(P* p, int index) {
    if(index < 0 || index >= p->taskNum)
        return false;
    
    T *ptr = p->headTask;
    for(int i = 0;i < index;i++)
        ptr = ptr->nextTask;
    
    printf("*** enter the importance ***");
    int imp = 1;
    scanf("%d",&imp);
    
    if(imp < 1 || imp > 3)
        printf("*** invalid importance ***");
    else
        ptr->importance = imp;
    
    return true;
}

void createTask(P *p)
	{
		char tName[NAME_SIZE] = "";
		char tLabel[LABEL_SIZE] = "";
		date tSTime;
		date tETime;
		int  tImportance;

		printf("name: ");
		scanf("%29s", tName);
		printf("label: ");
		scanf("%99s", tLabel);
		printf("startTime\nyear:");
		scanf("%d", &tSTime.year);
		printf("month: ");
		scanf("%d", &tSTime.month);
		printf("day: ");
		scanf("%d", &tSTime.day);
		printf("endTime\nyear:");
		scanf("%d", &tETime.year);
		printf("month: ");
		scanf("%d", &tETime.month);
		printf("day: ");
		scanf("%d", &tETime.day);
        printf("importance:");
		scanf("%d", &tImportance);

		task newTask;
        memset(&newTask, 0, sizeof(task));
		strcpy(newTask.name, tName);
		strcpy(newTask.label, tLabel);
		copyDate(&newTask.sTime, tSTime);
		copyDate(&newTask.eTime, tETime);
        newTask.importance = tImportance;
        
        T *temp = (T *)malloc(sizeof(struct task));
        T *ptr = p->headTask;
        
        copyTask(temp, newTask);
        if(ptr == NULL){
            p->headTask = temp;
        }
        else{
            while(ptr->nextTask)
                ptr = ptr->nextTask;
            
            ptr->nextTask = temp;
            temp->previousTask = ptr;
            p->taskNum++;
        }
    }

void instruction( ){
    printf("*** 1 to see time       ***\n");//查看时间
    printf("*** 2 to see today task ***\n");//查看今日代办任务
    printf("*** 3 to check plan     ***\n");//计划编辑
    printf("*** 4 to open file      ***\n");//打开文件
    printf("*** 5 to save file      ***\n");//储存文件
    printf("*** 6 to get help       ***\n");//获得帮助
    printf("*** 0 to end            ***\n");//结束程序
}//DONE

void planInstruction( ){
    printf("*** 1 to print plans    ***\n");//打印所有计划
    printf("*** 2 to edit a plan    ***\n");//编辑某个计划
    printf("*** 3 to create a plan  ***\n");//创建新的计划
    printf("*** 4 to delete a plan  ***\n");//删除某个计划
    printf("*** 5 to get help       ***\n");//获得帮助
    printf("*** 0 to back           ***\n");//返回主界面
}//DONE

void ePlanInstruction(){
    printf("*** 1 to set name      ***\n");//设置计划名字
    printf("*** 2 to set label     ***\n");//设置计划标签
    printf("*** 3 to set startTime ***\n");//设置计划起始时间
    printf("*** 4 to set endTime   ***\n");//设置计划截止时间
    printf("*** 5 to create task   ***\n");//创建新的任务
    printf("*** 6 to delete task   ***\n");//删除某个任务
    printf("*** 7 to edit task     ***\n");//编辑某个任务
    printf("*** 8 to get help      ***\n");//获得帮助
    printf("*** 0 to back          ***\n");//返回计划界面
}//DONE

void eTaskInstruction(){
    printf("*** 1 to set name       ***\n");//设置任务名字
    printf("*** 2 to set label      ***\n");//设置任务标签
    printf("*** 3 to set stratTime  ***\n");//设置任务起始时间
    printf("*** 4 to set endTime    ***\n");//设置任务截止时间
    printf("*** 5 to set importance ***\n");//设置任务重要性
    printf("*** 6 to print task     ***\n");//打印任务信息
    printf("*** 7 to get help       ***\n");//获得帮助
    printf("*** 0 to back           ***\n");//返回
}//DONE
